Введение
MyBlog – это легковесное асинхронное веб-приложение для ведения личного блога и галереи нейросетевых артов. Построено на базе фреймворка FastAPI. Основная идея проекта – полная автономность, отсутствие тяжелых внешних зависимостей (баз данных) и прямая работа с файловой системой. Это делает проект идеальным для self-hosted развертывания.
1. Архитектура и серверная логика: main.py
1.1 Инфраструктурные решения
Проект спроектирован с учетом работы за Reverse Proxy (Nginx/Traefik).
- Middleware для подпапок:
@app.middleware("http")
async def add_proxy_headers(request: Request, call_next):
path_prefix = request.headers.get("X-Forwarded-Prefix")
if path_prefix:
request.scope["root_path"] = path_prefix
return await call_next(request)
Это критически важный узел. Если сайт крутится не в корне домена (например, domain.com/blog/), заголовки X-Forwarded-Prefix позволяют FastAPI корректно генерировать внутренние ссылки.
- Загрузка окружения: Реализована функция
load_env_file, которая парсит.envбез сторонних библиотек (типаpython-dotenv). Это минус одна зависимость в проекте и плюс к безопасности.
1.2 Работа с базой данных (Flat-file DB)
Архитектура проекта исключает SQL. Мы используем Flat-file approach:
- Статьи: Хранятся как
.mdфайлы в папке/posts. - Метаданные галереи: Хранятся в
prompts.json. - Медиа: Лежат в
static/gallery.
Плюсы: Бекап блога – это просто копирование папки. Нет оверхеда на коннекты к БД.
Минусы: Отсутствие транзакционности. При массовой записи возможен Race Condition, но для персонального блога это не является проблемой.
1.3 Система авторизации
Реализована через SessionMiddleware на базе зашифрованных Cookies.
- Функция
require_auth(request)выступает в роли защитного барьера (Guard) для всех деструктивных действий (удаление статей, загрузка файлов). - Логика редиректов: При входе система запоминает
Referer, что позволяет возвращать пользователя именно туда, где он был до авторизации.
1.4 Контент-пайплайн (Markdown)
html = markdown.markdown(text, extensions=['fenced_code', 'tables', 'codehilite'])
Сервер использует динамический рендеринг: при каждом запросе выбранный .md файл считывается с диска и преобразуется в HTML. Это избавляет от необходимости хранить базу данных с HTML-копиями статей и позволяет обновлять контент простым редактированием файла на сервере.
Техническое уточнение:
В текущем вызове markdown.markdown(text, extensions=['fenced_code', 'tables', 'codehilite']) расширение codehilite является избыточным (рудиментом), так как выполняет разметку синтаксиса на стороне сервера без последующей стилизации на фронтенде. Для оптимизации и очистки выходного HTML данный модуль может быть удалён без потери визуального качества.
2. Функциональные блоки (Эндпоинты)
2.1 Галерея и Промты
Галерея – это не просто список картинок. Сервер связывает файлы изображений с их текстовыми описаниями (промтами):
GET /gallery: Сканирует директорию, сортирует файлы по времени изменения (st_mtime) и сопоставляет с данными из JSON.POST /gallery/prompt_save: Обновляет описания. Поддерживается только админом.
2.2 Загрузка контента
Для статей и галереи реализованы асинхронные загрузчики:
- Безопасность имен: Используется
re.sub(r'[^\w\s\-\.\[\]]', '', name)для очистки имен файлов. Это предотвращает атаки типа Path Traversal. - Валидация типов: Проверка идет как по
content_type, так и по расширению файла (белый список: jpg, jpeg, png, gif, mp4).
2.3 Трюки с вёрсткой (Jinja2 Filters)
Внедрен кастомный фильтр insert_zwsp:
templates.env.filters['insert_zwsp'] = insert_zero_width_spaces
Он автоматически вставляет невидимые пробелы в длинные строки (более 10 символов), которые не являются HTML-тегами. Это спасает мобильную вёрстку от "разрывов" из-за длинных слов или ссылок.
3. Обоснование стека
- FastAPI: Минималистичен, быстр, асинхронен. Позволяет легко расширять проект.
- Uvicorn: ASGI-сервер, обеспечивающий высокую пропускную способность.
- Markdown: Выбран как стандарт де-факто для написания заметок (идеальная совместимость с Obsidian).
- Jinja2: Серверный рендеринг исключает необходимость в сложных фронтенд-фреймворках, сохраняя при этом интерактивность.
4. Итоги и эксплуатация
- Производительность: Блог работает экстремально быстро за счет отсутствия запросов к сторонним сервисам и базам данных.
- Масштабируемость: Проект рассчитан на личное использование. При количестве статей > 1000 может потребоваться кэширование списка постов.
- Безопасность: Реализована базовая защита от перебора паролей (через сессии) и контроль доступа к файловой системе.
Архитектурный вывод: Это надежное монолитное решение "всё в одном", которое легко разворачивается через Docker или просто как системный процесс.
2. Клиентская часть: main.html (Главная страница)
2.1 UI/UX и дизайн-система
Дизайн выполнен в стиле Modern Dark Minimalism. Основной упор сделан на контенте, при этом интерфейс визуально перекликается с профессиональными IDE и инструментами продуктивности.
- Адаптивность «Flexy-стандарт»: Навигация использует технику горизонтального скролла на мобильных устройствах (
overflow-x: auto), что позволяет уместить множество ссылок без загромождения экрана. - Интерактивные элементы: Кнопки и карточки статей имеют плавные транзишны (
0.3s) и эффекты трансформации (translateY), что дает пользователю четкий фидбек при взаимодействии. - Типографика: Использование шрифта Tahoma и функции
clamp()для заголовков обеспечивает отличную читаемость как на огромных 4K мониторах, так и на смартфонах.
2.2 Умная система категорий (The Tag System)
Одной из самых интересных фишек является автоматический парсинг категорий из названий файлов.
- Логика: Если файл статьи называется
[Софт] Прошивка.md, фронтенд автоматически выделит категорию «Софт». - Код:
const match = name.match(/^\[(.*?)\]/);
if (match) {
categories.add(match[1]);
item.dataset.category = match[1].toLowerCase();
}
Это избавляет админа от необходимости вручную прописывать теги в базе данных. Система сама строит дерево категорий на лету.
2.3 Динамическая фильтрация и поиск
Вместо того чтобы нагружать сервер запросами при каждом вводе буквы, поиск реализован на стороне клиента (Client-side Filtering).
- Поиск: Работает мгновенно через
includes()по атрибутамdata-name. - Категории: Переключаются без перезагрузки страницы. Пользователь видит результат сразу.
- Счётчик: Элемент
#articles-countдинамически обновляется, показывая количество найденных записей. Это отличный UX-паттерн.
2.4 AJAX-управление (Админ-панель)
Для авторизованных пользователей предусмотрена возможность управления архивом.
- Safe Delete: Удаление статей происходит через
fetch()с подтверждениемconfirm(). После успешного удаления элемент исчезает из DOM без перезагрузки всей страницы (el.remove()), что субъективно делает интерфейс очень быстрым. - CSRF-защита (базовая): Использование заголовка
X-Requested-With: XMLHttpRequestпозволяет серверу отличать автоматизированные запросы от ручных переходов.
2.5 Технические особенности вёрстки
- CSS Grid: Список постов использует
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)). Это самая современная техника, которая автоматически распределяет карточки по ширине, не оставляя пустых мест. - Zero-runtime Iconography: Иконки постов (класс
.post-icon) отрисованы на чистом CSS (псевдоэлементы::beforeи::after). Это экономит лишние HTTP-запросы к SVG или шрифтовым иконкам и гарантирует мгновенную отрисовку.
3. Обоснование архитектурных решений фронтенда
- No Framework (Vanilla JS): Использование чистого JavaScript \u2014 осознанный выбор. Для такого функционала React или Vue были бы избыточны (overkill), а текущий код весит всего пару килобайт и работает быстрее любого фреймворка.
- Jinja2 Hydration: Начальный список статей рендерится сервером, а затем "подхватывается" скриптами для фильтрации. Это сохраняет SEO-показатели (поисковики видят все ссылки) при полной интерактивности.
- LocalStorage Bypass: В отличие от предыдущих модулей, здесь данные полностью контролируются сервером, а фронтенд лишь управляет их отображением.
Плюсы:
- Мгновенная реакция на действия пользователя.
- Идеальное отображение на мобильных устройствах.
- Отсутствие "тяжелого" JS-бандла.
Минусы:
- При очень большом списке статей (более 1000) клиентский поиск может потреблять больше ресурсов CPU, чем серверный. Но для личного блога это недостижимый предел.
Полный разбор архитектуры MyBlog: Article View Engine
Этот модуль (article.html) отвечает за рендеринг и обогащение контента. Основная фишка заключается в Post-processing на стороне клиента. Мы не просто выводим HTML, мы его дорабатываем скриптами для лучшего UX
1. Клиентская обработка контента (Post-processing)
1.1 Оживление ссылок
1.1 Оживление ссылок
Стандартный парсер Markdown может игнорировать текстовые URL и не превращать их в кликабельные элементы. Данный скрипт автоматизирует процесс: он находит в тексте строки, соответствующие паттерну https://, и оборачивает их в активные HTML-ссылки. Это гарантирует корректную навигацию, даже если автор забыл использовать синтаксис разметки.
const urlRegex = /(?<!["=])(https?:\/\/[^\s<]+)/g;
articleBody.querySelectorAll('p, li, td').forEach(el => {
el.innerHTML = el.innerHTML.replace(urlRegex, (url) => {
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`;
});
});
Инженерная деталь: Используется Lookbehind (?<!["=]), чтобы не испортить теги, где URL уже находится внутри атрибутов src или href.
1.2 Парсинг категорий из заголовка
Здесь применяется логика визуальных меток. Если заголовок статьи имеет вид [OS] Настройка Windows, скрипт выделяет тег [OS], преобразует его в отдельный графический элемент над названием, а основной текст очищает от лишних скобок. Такой подход позволяет сохранять профессиональную структуру статьи, оставляя исходные файлы на диске удобными для чтения.
2. Работа с кодом и таблицами
2.1 Code Blocks & Copy Engine
Любой блок кода автоматически оборачивается в контейнер .code-block, куда инжектится кнопка копирования.
- UX-фишка: При клике иконка меняется на галочку (чек-марк) и подсвечивается акцентным цветом на 2 секунды. Это дает понять, что код уже в буфере.
- Шрифты: Для кода жестко прописаны модульные моноширинные шрифты (
Consolas,Monaco), что критично для айтишника.
Таблицы в вебе часто создают проблемы. Здесь реализовано изящное решение: скрипт находит все таблицы и оборачивает их в div.table-wrapper с overflow-x: auto. На смартфонах таблица не ломает вёрстку, а получает аккуратную горизонтальную прокрутку.
Таблицы в вебе – это один из самых «капризных» элементов. Если их просто оставить как есть, они напрочь ломают мобильную вёрстку, растягивая страницу по горизонтали так, что пользователю приходится скроллить влево-вправо.
1. Серверный этап (Генерация)
Расширение tables в библиотеке markdown превращает стандартную Markdown-разметку:
| Заголовок 1 | Заголовок 2 |
|-------------|-------------|
| Текст 1 | Текст 2 |
в чистый HTML-код: теги <table>, <thead>, <tbody>, <tr> (строки) и <td> (ячейки). Сами по себе эти теги не умеют подстраиваться под размер экрана.
2. Фронтенд-этап (Адаптация)
Поскольку таблицы «дубовые» по своей природе, в твоём коде (в модуле article.html) используется специальный JS-скрипт.
Что он делает (алгоритм):
- Находит все таблицы (
<table>), которые сгенерировал сервер. - Проверяет их ширину. Если таблица не влезает в экран, скрипт не даёт ей «разорвать» дизайн.
- Он оборачивает каждую таблицу в специальный контейнер
<div>со свойствомoverflow-x: auto.
Как это выглядит для пользователя:
Вместо того чтобы вся страница начала «болтаться» из стороны в сторону, сама статья остаётся стабильной, а внутри неё появляется аккуратная область с таблицей, которую можно скроллить пальцем влево-вправо. Это называется Responsive Data Tables.### Итог для твоего разбора:
Таблицы в твоём проекте – это гибридное решение.
- Markdown
tablesотвечает за структуру и данные. - Vanilla JS отвечает за то, чтобы эти данные не превратили чтение статьи на телефоне в кошмар.
Это классический пример того, как минималистичный бэкенд дополняется умным фронтендом для обеспечения безупречного UX (User Experience).
3. Дизайн и типографика статьи
- Визуальный акцент: Заголовки
H2имеют левый border (5px solid) цветаaccent. Это помогает сканировать взглядом структуру длинных технических текстов. - Читаемость:
line-height: 1.75(увеличенный межстрочный интервал) и размер шрифта1.1remвыбраны для того, чтобы глаза не уставали при чтении объемных гайдов. - Dark Mode Optimization: Текст имеет цвет
#cbd5e1(не чисто белый), что снижает контрастную нагрузку на глаза в темноте.
4. Интеграция с нативной системой (Share API)
Кнопка Поделиться не просто копирует URL, она выполняет нормализацию:
const prettyUrl = decodeURIComponent(window.location.href).replace(/ /g, '%20');
Это гарантирует, что если в названии статьи есть кириллица или пробелы, ссылка в буфере будет валидной и рабочей для любого мессенджера.
5. Безопасность и управление
- Safe Delete: Кнопка удаления доступна только владельцу (
is_auth) и защищена двойным барьером: проверкой на сервере иconfirmна фронте. - Noopener/Noreferrer: Все внешние ссылки, созданные скриптом, получают эти атрибуты. Это защищает от атак типа
tabnabbingи не передает данные о твоем блоге сторонним ресурсам.
Вердикт по модулю Article
Этот шаблон превращает простой текстовый файл в полноценную веб-страницу.
Главный плюс: Весь функционал (копирование кода, бейджи, ссылки) работает автономно и мгновенно.
Минус: Если в статье будет 500 блоков кода, инициализация 500 кнопок копирования может занять доли микросекунды (что на самом деле незаметно, но мы же задроты, верно?).
Полный разбор архитектуры MyBlog: Gallery & Masonry Engine
Галерея предназначена для отображения нейросетевых артов и видео. Основная техническая сложность здесь – работа с контентом разной высоты без создания визуальных дыр в сетке.
1. Masonry Grid: Математика вёрстки
Вместо использования тяжелых библиотек (типа Isotope или Masonry.js), в проект интегрирован самописный легковесный алгоритм на Vanilla JS.
- Логика работы (
resizeInstance): - Система определяет количество колонок в зависимости от ширины экрана (от 1 до 3).
- Создаётся массив
colHeights, инициализированный нулями. - Для каждого элемента вычисляется его позиция: он всегда встаёт в ту колонку, которая в данный момент является самой короткой.
- Используется
translate3dдля перемещения карточек – это задействует аппаратное ускорение GPU, делая анимацию плавной (60 FPS), в отличие от измененияtop/left.
const minH = Math.min(...colHeights), idx = colHeights.indexOf(minH);
item.style.transform = `translate3d(${idx * (itemWidth + gap)}px, ${minH}px, 0)`;
2. Работа с медиа-контентом
2.1 Поддержка видео
Галерея нативно поддерживает формат MP4. Для экономии ресурсов и создания "живого" эффекта превью:
- Видео воспроизводятся автоматически (
autoplay), без звука (muted) и по кругу (loop). - Атрибут
playsinlineгарантирует, что видео не будет разворачиваться на весь экран при старте на iPhone.
2.2 Умный Лайтбокс (Просмотрщик)
Реализована собственная система предпросмотра. При клике на изображение создаётся оверлей с динамическим блюром (backdrop-filter: blur(15px)).
Инженерная деталь: Контент внутри лайтбокса адаптивен (max-height: 92vh). Это предотвращает появление полос прокрутки внутри модального окна на маленьких экранах.
3. Интеграция с данными ИИ (Prompt Management)
Каждая карточка в галерее – это контейнер для метаданных.
- Prompt Area: Текстовое поле с промтом по умолчанию скрыто и использует моноширинный шрифт
Consolasдля удобного чтения параметров генерации. - AJAX-сохранение: Для админа реализована возможность редактировать промты прямо "на лету" через
FormDataи эндпоинт/gallery/prompt_save. - Copy Engine: Быстрый механизм копирования промта для тех, кто хочет повторить генерацию.
4. Дизайн и UX-фишки
- Глубина и Ховеры: При наведении на карточку срабатывает
scale(1.08)для изображения и меняется цвет границы (box-shadow). Это создаёт ощущение интерактивности. - Бейджи: Система автоматически вешает маркеры (IMAGE / VIDEO), чтобы пользователь понимал тип контента до взаимодействия.
- Унифицированная навигция: Как и во всём проекте, на мобайле меню навигации скроллится горизонтально, не ломая структуру страницы.
5. Плюсы и минусы решения
Плюсы:
- Zero Library: Отсутствие внешних JS-зависимостей делает страницу экстремально легкой.
- GPU acceleration: Плавная перестройка сетки при изменении размера окна браузера.
- Flexibility: Галерея одинаково хорошо работает как с горизонтальными, так и с вертикальными артами.
Минусы:
- Initial Load: Функция
resizeInstanceдолжна ждать полной загрузки изображений, чтобы узнать их высоту (window.onload). На очень медленном интернете сетка может "прыгнуть" во время инициализации. Решается введением фиксированных пропорций для картинок (aspect-ratio), если они известны заранее.
Полный разбор MyBlog: Система доступа и управления контентом
1. Модуль авторизации: login.html
Страница входа выполнена в стиле Cyber-Dark. Здесь нет ничего лишнего, только функционал, защищённый логикой сессий.
1.1 Механизм редиректов (The "Next" Pattern)
Одной из ключевых особенностей является использование переменной next_url.
- Логика: Если ты пытаешься зайти в галерею будучи неавторизованным, сервер перекидывает тебя на
/login?next=gallery. После ввода пароля страница не просто выкинет тебя на главную, а вернёт именно в галерею. - Инженерная реализация: Значение передаётся через скрытое поле формы (
<input type="hidden">), обеспечивая бесшовный пользовательский опыт (UX).
1.2 Фронтенд-валидация
- Zoom Prevention: Для
inputустановленfont-size: 16px. Это маленькая, но важная деталь для iOS-устройств – при меньшем размере шрифта браузер Safari принудительно увеличивает масштаб страницы при фокусе на поле, что ломает вёрстку. Здесь это исправлено.
2. Модули загрузки: upload_article.html / upload_gallery.html
Это интерфейсы для взаимодействия с файловой системой сервера через абстракцию FastAPI UploadFile.
2.1 Drag-and-Drop и Пакетная обработка
Система поддерживает одновременную загрузку нескольких файлов (multiple).
- Для галереи: Можно закинуть сразу 20-30 артов. Фронтенд отправит их пачкой, а сервер в цикле разложит по местам, проверяя расширения.
- Для статей: Принимаются только файлы с расширением
.md. Если попытаться загрузить что-то другое, сервер проигнорирует файл (безопасность!).
2.2 Логика очистки имен (Sanitization)
На странице загрузки статей реализована важная проверка:
safe_name = re.sub(r'[^\w\s\-\.\[\]]', '', file.filename).strip()
Это защищает сервер от инъекций в именах файлов. Если файл называется [AI]; rm -rf /; .md, он превратится в безобидный [AI] rm -rf .md.
3. Административные операции (Destructive Actions)
Проект включает в себя функции \u00abядерного уничтожения\u00bb данных для быстрой очистки архива.
delete_all: Эти эндпоинты защищены двойным барьером.- Кнопка на фронте вызывает
confirm(). - Декоратор
require_authна бэкенде проверяет наличие активной сессии. - Асинхронное удаление: При удалении одной статьи используется
fetch, чтобы не обновлять страницу – это современный стандарт (SPA-подобное поведение). Полный разбор архитектуры MyBlog: Data Ingestion (Загрузка данных)
Этот раздел посвящён страницам upload_gallery.html и upload_article.html. С точки зрения архитектуры – это порты ввода данных, реализующие паттерн Client-side File Processing перед отправкой на FastAPI.
1. Стек и UX-инженерия
Обе страницы используют единый визуальный код, но разные механизмы валидации в зависимости от типа контента.
1.1 Универсальный Drag-and-Drop
Вместо стандартных и скучных кнопок выбора файлов реализована интерактивная зона – dropzone.
- Механика: Использование событий
ondragover,ondragleaveиondrop. При наведении область подсвечивается (scale(1.02)и смена цвета рамки), обеспечивая визуальный отклик (Affordance). - Пакетный режим: Атрибут
multipleвinput type="file"позволяет за один проход загрузить весь архив статей или пачку сгенерированных артов.
1.2 Асинхронные пайплайны загрузки
Для отправки данных используется асинхронный fetch с объектом FormData.
Инженерный профит: Страница не перезагружается в процессе отправки. Пользователь видит статус ("Загрузка на сервер...", "Успешно!") в реальном времени.
2. Глубокий разбор: Загрузка в Галерею (upload_gallery)
Этот модуль сложнее, так как он работает с бинарными данными (изображения и видео).
2.1 Двойная валидация
Перед отправкой фронтенд выполняет первичную проверку:
- По MIME-типу:
['image/jpeg', 'image/png', 'image/gif', 'video/mp4'].includes(file.type). - По расширению: На случай, если браузер некорректно определил тип файла.
Это экономит трафик: если пользователь случайно выберет .zip архив, он получит ошибку мгновенно, без ожидания ответа от сервера.### 2.2 Обработка результатов
После загрузки сервер возвращает JSON со списком результатов. Скрипт анализирует его:
const successCount = data.results.filter(r => r.status === 'ok').length;
Это позволяет реализовать частичный успех: если из 10 файлов 8 загрузились, а 2 были повреждены, пользователь узнает точное количество.
3. Глубокий разбор: Загрузка Статей (upload_article)
Этот модуль адаптирован под текстовый Workflow (Obsidian/Notepad++).
3.1 Фильтрация формата .md
В отличие от галереи, здесь кнопка "Опубликовать" (#uploadBtn) изначально заблокирована (disabled). Она "оживает" только тогда, когда в массив selectedFiles попадают файлы с расширением .md.
selectedFiles = Array.from(files).filter(f => f.name.toLowerCase().endsWith('.md'));
3.2 Автоматизация редиректа
После успешной публикации статьи пользователь автоматически перенаправляется на главную страницу блога через 1.5 секунды. Этого времени достаточно, чтобы увидеть сообщение об успехе, после чего система сразу показывает обновленный список постов.
4. Обоснование инфраструктурных решений
- No Heavy Dependencies: Весь функционал drag-and-drop написан на чистом JS без библиотек типа Dropzone.js. Это гарантирует отсутствие конфликтов и минимальный размер страницы (~3-5 Кб).
- Security by Design:
- На фронтенде ограничены типы файлов (
accept=".md",accept="image/*"). - На бэкенде (как мы помним из разбора
main.py) стоит повторная проверка. Это классическая стратегия Defense in Depth (эшелонированная оборона). - Mobile-First: На мобильных устройствах зона
dropzoneадаптируется по высоте, а кнопки выбора файлов становятся крупнее, чтобы по ним было легко попасть пальцем.
5. Плюсы и минусы загрузчиков
Плюсы:
- Высокая скорость работы за счёт асинхронности.
- Прозрачная индикация процесса (пульсирующая анимация текста).
- Поддержка современных форматов и пакетной загрузки.
Минусы:
- Отсутствие визуальных превью (thumbnails) перед загрузкой в галерею. Это сознательное упрощение в пользу легкости кода, так как обычно пользователь знает, что именно он загружает.
Модули загрузки превращают статичное хранилище в динамическую платформу. Использование fetch и FormData делает процесс публикации контента почти мгновенным, превращая MyBlog в полноценную CMS (Content Management System) для личного использования.
Полный разбор архитектуры MyBlog: Authentication Gate
Здесь реализован классический паттерн Stateful Auth, где сервер контролирует доступ на основе сессионных кук, а фронтенд обеспечивает удобную точку входа.
1. UX-инженерия и "Mobile First"
Как и во всём проекте, здесь соблюдён строгий стандарт адаптивности.
- Инпут-хак для iOS: Для всех полей ввода установлен
font-size: 16px. Это решение исключает паразитное масштабирование (авто-зум) в браузере Safari на iPhone, которое обычно портит вёрстку при фокусе на текстовом поле. - Интерактивные состояния: Поля ввода (
input) подсвечиваются мягким синим свечением (box-shadow), а кнопка входа реагирует на ховер подъёмом по оси Y. Это даёт ощущение "упругости" интерфейса.
2. Логика перенаправлений (Next-параметр)Особое внимание уделено сохранению пути пользователя:
<input type="hidden" name="next_url" value="{{ next_url }}">
Техническая ценность: Если вы, будучи неавторизованным, попытаетесь зайти в панель загрузки статьи, система перекинет вас на логин, но запомнит ваш изначальный запрос. После успешного входа FastAPI прочитает это скрытое поле и вернёт вас именно туда, куда ты шёл. Это избавляет от лишних кликов и навигации по меню заново.
- Автозаполнение: Использование атрибутов autocomplete="username" и autocomplete="current-password" помогает менеджерам паролей (Bitwarden, Google Passwords) корректно распознавать поля. Для стабильной работы на мобильных устройствах рекомендуется всегда связывать label и input через атрибут id.
-
Индикация ошибок: Блок .error отображается сервером (Jinja2) только при неудачной аутентификации. Он оформлен цветом #ef4444 (стандарт Soft Red) и имеет полупрозрачный фон для удобства чтения в тёмной теме. ## 4. Дизайн-код
-
Визуальная изоляция: Карточка логина (
.login-container) имеет чёткую границу и тень, что отделяет форму от общего фона и фокусирует внимание пользователя на действии. - Транзишны: Плавность переходов (
var(--transition)) во всём проекте делает интерфейс отзывчивым и современным.
Общий итог по проекту (The Big Picture)
Мы разобрали MyBlog сверху донизу:
- Ядро (FastAPI): Асинхронная мощь и работа с плоскими файлами (Markdown/JSON) вместо тяжелых БД.
- Фронтенд (Vanilla JS + Jinja2): Молниеносная скорость работы, отсутствие лишних зависимостей и библиотек.
- Галерея (Masonry Engine): Умная сетка на GPU-ускоренных трансформациях.
- Статьи (Markdown Engine): Автоматическая конвертация заметок из Obsidian в живые статьи с копированием кода и адаптивными таблицами.
- Админка (Data Ingestion): Удобная загрузка файлов через Drag-and-Drop и безопасная авторизация.